﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using BMC.ARSystem;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Wicresoft.EKA.NRemedy.Test.Util;
using System.Linq.Expressions;

namespace Wicresoft.EKA.NRemedy.Test
{
    /// <summary>
    /// Mock a ARServer to Test Linq to NRemedy
    /// </summary>
    public class ARServerFactory2 : ARServerFactoryDefault
    {
        public new IARServer GetARServer(params object[] param)
        {
            return new ARServerFactory2.Server();
        }

        private class Server : IARServer
        {
            MethodInfo mi = null;

            List<RegularForm> mockRegularForm = new List<RegularForm>() { 
                new RegularForm{ Submitter = "Parker", CheckBoxField = RegularForm.CheckBoxField_Enum.Default1, IntegerField = 1,DecimalNumberField = 1.0m,DateTimeField = new DateTime(2012,12,21) },
                new RegularForm{ Submitter = "Parker", CheckBoxField = RegularForm.CheckBoxField_Enum.Default2, IntegerField = 2,DecimalNumberField = 2.0m ,DateTimeField = new DateTime(2012,1,1) },
                new RegularForm{ Submitter = "Parker2", CheckBoxField = RegularForm.CheckBoxField_Enum.Default2, IntegerField = 3,DecimalNumberField = 3.0m ,DateTimeField = new DateTime(2012,3,1) },
                new RegularForm{ Submitter = "Parker2", CheckBoxField = RegularForm.CheckBoxField_Enum.Default1, IntegerField = 4,DecimalNumberField = 4.0m,DateTimeField = new DateTime(2012,3,1)  },
                new RegularForm{ Submitter = "Parker", CheckBoxField = RegularForm.CheckBoxField_Enum.Default1, IntegerField = 5,DecimalNumberField = 5.0m ,DateTimeField = new DateTime(2012,5,2) },
                new RegularForm{ Submitter = "Parker", CheckBoxField = RegularForm.CheckBoxField_Enum.Default1, IntegerField = 6,DecimalNumberField = 6.0m ,DateTimeField = new DateTime(2012,12,14) }
            };

            public void Login(string server, string user, string password, string authentication)
            {
                PropertyInfo pi = typeof(RegularForm).GetProperty("Request_ID", BindingFlags.Instance | BindingFlags.Public);
                for (int i = 0; i < mockRegularForm.Count; i++)
                {
                    pi.SetValue(mockRegularForm[i], i.ToString(), null);

                }

                return;
            }

            public bool ServerAlive
            {
                get { return true; }
            }

            public void Logout()
            {
                return;
            }

            public System.Collections.ArrayList GetListForm()
            {
                throw new NotImplementedException();
            }

            public ARForm GetForm(string name)
            {
                throw new NotImplementedException();
            }

            public System.Collections.ArrayList GetListField(string formName)
            {
                throw new NotImplementedException();
            }

            public Field GetField(string formName, uint id)
            {
                throw new NotImplementedException();
            }

            public void BeginBulkEntryTransaction()
            {
                return;
            }

            public System.Collections.ArrayList CancelBulkEntryTransaction()
            {
                return null;
            }

            public System.Collections.ArrayList SendBulkEntryTransaction()
            {
                return null;
            }

            public string CreateEntry(string form, FieldValueList fieldValueList)
            {
                throw new NotImplementedException();
            }

            public void DeleteEntry(string form, string entryId, int deleteOption = 0)
            {
                throw new NotImplementedException();
            }

            public void SetEntry(string form, string entryId, FieldValueList fieldValueList)
            {
                throw new NotImplementedException();
            }

            public void SetEntryByQuery(string formName, string qualification, BMC.ARSystem.Server.SetEntryByQuery_NoMatchOption noMatchOption, BMC.ARSystem.Server.SetEntryByQuery_MultiMatchOption multiMatchOption, FieldValueList fieldValueList, bool useLocale = false)
            {
                throw new NotImplementedException();
            }

            //Must implement
            public FieldValueList GetEntry(string form, string entryId, FieldIdList fieldIdList)
            {
                //Must use RegularForm
                Assert.AreEqual("RegularForm", form);
                if (fieldIdList == null)
                {
                    RegularForm rf = mockRegularForm.ElementAt(Int32.Parse(entryId));
                    FieldValueList fv = new ModelBinder<RegularForm>().UnBind(rf);
                    //modify enum field
                    fv[536870937u] = (int)rf.DropDownListField;
                    fv[536870938u] = (int)rf.RadioButtonField;
                    fv[536870939u] = (int)rf.CheckBoxField;
                    fv[7u] = (int)rf.Status;
                    fv[1] = entryId;
                    fv[3] = DateTime.Now;
                    fv[5] = entryId;
                    fv[6] = DateTime.Now;
                    return fv;
                }
                else
                {
                    RegularForm rf = mockRegularForm.ElementAt(Int32.Parse(entryId));
                    FieldValueList fv = new ModelBinder<RegularForm>().UnBind(rf);
                    //modify enum field
                    fv[536870937u] = (int)rf.DropDownListField;
                    fv[536870938u] = (int)rf.RadioButtonField;
                    fv[536870939u] = (int)rf.CheckBoxField;
                    fv[7u] = (int)rf.Status;
                    fv[1] = entryId;
                    fv[3] = DateTime.Now;
                    fv[5] = entryId;
                    fv[6] = DateTime.Now;

                    FieldValueList list2 = new FieldValueList();
                    foreach(uint id in fieldIdList)
                    {
                        list2.Add(id,fv[id]);
                    }

                    return list2;
                }
            }


            //Must implement
            //Must return <EntryDescription>
            //At least contains EntryId
            public System.Collections.ArrayList GetListEntry(string formName, string qualification, FieldIdList fieldIdList = null)
            {
                //Must use RegularForm
                Assert.AreEqual("RegularForm", formName);
                List<RegularForm> resultlist = null;
                if (string.IsNullOrEmpty(qualification))
                    resultlist = mockRegularForm;
                else
                {
                    ExpressionBuilder eb = new ExpressionBuilder();
                    Expression exp = eb.ConventExpressoin(qualification, typeof(RegularForm));

                    var lamda = Expression.Lambda<Func<RegularForm, bool>>(((LambdaExpression)exp).Body, ((LambdaExpression)exp).Parameters);
                    resultlist = mockRegularForm.Where(lamda.Compile()).ToList();
                }


                System.Collections.ArrayList al = new System.Collections.ArrayList();

                for (int i = 0; i < resultlist.Count(); i++)
                {
                    al.Add(CreateEntryDescription(
                            resultlist.ElementAt(i).Request_ID,
                            string.Empty
                            )
                        );
                }


                return al;
            }

            //because EntryDescription has only internal construct
            private EntryDescription CreateEntryDescription(string entryId, string description)
            {
                if (mi == null)
                    mi = typeof(EntryDescription).GetMethod("createInstance", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
                if (mi == null) throw new NullReferenceException("mi");
                return mi.Invoke(null, new object[] { new object[] { new object[] { entryId }, description }, null })
                    as EntryDescription;

            }


            public System.Collections.Hashtable GetAllFields(string form)
            {
                throw new NotImplementedException();
            }

            public void Dispose()
            {
                throw new NotImplementedException();
            }

            string IARServer.Server
            {
                get { throw new NotImplementedException(); }
            }

            public string User
            {
                get { throw new NotImplementedException(); }
            }

            public string Password
            {
                get { throw new NotImplementedException(); }
            }

            public string Authentication
            {
                get { throw new NotImplementedException(); }
            }

            public bool IsInPool
            {
                get
                {
                    throw new NotImplementedException();
                }
                set
                {
                    throw new NotImplementedException();
                }
            }


            public void ReLogin()
            {
                throw new NotImplementedException();
            }


            public void SetContextContainer(ARLoginContext context)
            {
                throw new NotImplementedException();
            }


            public BMC.ARSystem.Server BMCServer
            {
                get { throw new NotImplementedException(); }
            }


            public System.Collections.ArrayList GetPagedEntry(string formName, string qualification, EntryListFieldList fieldIdList, uint firstRetrieve, uint maxRetrieve, out int numMatches, System.Collections.ArrayList sortInfoList)
            {
                throw new NotImplementedException();
            }

            public System.Collections.ArrayList GetListEntry(string formName, string qualification, EntryListFieldList fieldIdList = null)
            {
                throw new NotImplementedException();
            }


            public System.Collections.ArrayList GetListField(string formName, int fieldType)
            {
                throw new NotImplementedException();
            }


            public ARLoginContext ContextContainer
            {
                get
                {
                    throw new NotImplementedException();
                }
                set
                {
                    throw new NotImplementedException();
                }
            }


            EntryFieldValueList IARServer.GetPagedEntry(string formName, string qualification, EntryListFieldList fieldIdList, uint firstRetrieve, uint maxRetrieve, out int numMatches, System.Collections.ArrayList sortInfoList)
            {
                throw new NotImplementedException();
            }

            EntryFieldValueList IARServer.GetListEntry(string formName, string qualification, EntryListFieldList fieldIdList = null)
            {
                throw new NotImplementedException();
            }

            public System.Collections.ArrayList GetListEntryDescription(string formName, string qualification)
            {
                throw new NotImplementedException();
            }
        }
    }
}
